#include <SPI.h>

#define VERSION         "1.0"
#define IDENT           "EEPROM_24P"

//数据
#define Data0 PIN_PC0
#define Data1 PIN_PC1
#define Data2 PIN_PD2
#define Data3 PIN_PD3
#define Data4 PIN_PD4
#define Data5 PIN_PD5
#define Data6 PIN_PD6
#define Data7 PIN_PD7

//595控制
#define DS    PIN_PB3 //数据位
#define LATCH PIN_PB2
#define SCK   PIN_PB5

#define CE PIN_PB1
#define OE PIN_PB0

#define A_11   PIN_PC2

#define V_11   PIN_PC4
#define V_OE   PIN_PC3

// ADC
#define P_A6   PIN_A6

#define delay125ns      {asm volatile("nop"); asm volatile("nop");}
#define delay250ns      {asm volatile("nop"); asm volatile("nop");asm volatile("nop"); asm volatile("nop");}

// Buffers
#define BUFF_LEN 64
#define CMD_LEN 22

uint8_t pageBuffer[BUFF_LEN];                  // page buffer
char    cmdBuffer[CMD_LEN];                    // command buffer


void setAddress(uint32_t addr,uint32_t chipId) {

  if(chipId==2732){
    digitalWrite(A_11, (addr>>11) & 1);
  }

  SPI.transfer16(addr & 0xffff);

  digitalWrite(LATCH,HIGH);
  digitalWrite(LATCH,LOW);

}


void setup() {
  //初始化
  pinMode(P_A6, INPUT);//ADC6
  pinMode(DS, OUTPUT);
  pinMode(SCK, OUTPUT);
  pinMode(LATCH, OUTPUT);
  digitalWrite(DS, LOW);
  digitalWrite(SCK, LOW);
  digitalWrite(LATCH, LOW);

  pinMode(A_11, OUTPUT);
  pinMode(V_11, OUTPUT);
  pinMode(V_OE, OUTPUT);
  digitalWrite(A_11, LOW);
  digitalWrite(V_11, LOW);
  digitalWrite(V_OE, LOW);

  pinMode(CE, OUTPUT);
  pinMode(OE, OUTPUT);
  digitalWrite(CE, HIGH);
  digitalWrite(OE, HIGH);

  read_mode();
  
  SPI.begin();
//  SPI.setClockDivider(SPI_CLOCK_DIV2);
//  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

//  Serial.begin(1000000);
  Serial.begin(115200);
//  Serial.begin(57600);
}


void loop() {
  //程序判断用
  Serial.println("Ready");
  readCommand();
  char cmd = cmdBuffer[0];                      //指令
  uint32_t chipId    = hexChip(cmdBuffer + 2);  //芯片
  uint32_t startAddr = hexWord(cmdBuffer + 10); //开始地址
  uint32_t endAddr   = hexWord(cmdBuffer + 16); //结束地址

  startAddr &= 0xffff;
  endAddr &= 0xffff;

  // 数据长度
  uint32_t dataLength = endAddr - startAddr + 1;

  switch(cmd) {
    case 'i':   Serial.println(IDENT); break;
    case 'v':   Serial.println(VERSION); break;
    case 't':   Serial.println("Ready"); break;
    case 'a':   Serial.println(get_voltage());break;
    case 'c':   Serial.println(true); break;

    //测试输入内容
    case 'r':   readChip(startAddr, dataLength, chipId); break;
    case 'w':   
      if (chipId==2716||chipId==2732) { //27-24p
        write27_24(startAddr, dataLength, chipId);
      } else {
        Serial.print(F("Write not support,chipId:"));
        Serial.println(chipId);
      }
      break;


    case 'x':   Serial.print(startAddr);Serial.print(" ");
                Serial.print(endAddr); Serial.print(" ");
                Serial.println(dataLength); break;
                
    case 'y':   
                digitalWrite(CE, LOW);
                digitalWrite(OE, LOW);
                break;
                
    default:    break;
  }
}


void setByte(uint32_t address, uint8_t dataa,uint32_t chipId){
  write_data_bus(dataa);
  setAddress(address,chipId);

  delay(1);

  if(chipId==2732){
    //2732使用OE高压
    digitalWrite(V_OE, HIGH);
  }else{
    //2716使用V11
    digitalWrite(V_11, HIGH);
  }

  digitalWrite(CE,LOW);
  delay(46);//45ms-55ms
  digitalWrite(CE,HIGH);

  digitalWrite(V_11, LOW);
  digitalWrite(V_OE, LOW);
}
// 根据地址读取数据
byte getByte(uint32_t addr,uint32_t chipId) {
  setAddress (addr,chipId);
  //读取延时
  delayMicroseconds(450);
  return read_data_bus();
}


// 读取芯片内容(读取的时候ce oe全部拉低，改变地址就可以输出)
void readChip(uint32_t addr, uint32_t count,uint32_t chipId) {
  //加上y参数的扩展地址
  read_mode();
  digitalWrite(CE, LOW);
  digitalWrite(OE, LOW);
  delay(1);

  while (count-- >0) {
    Serial.write(getByte(addr++,chipId));
  }

  digitalWrite(OE, HIGH);
  digitalWrite(CE, HIGH);
}

void write27_24(uint32_t addr, uint32_t total, uint32_t chipId) {
  for (uint8_t i = 0; i < BUFF_LEN; i++) {
    while (!Serial.available());
    pageBuffer[i] = Serial.read();
  }

  digitalWrite(OE, HIGH);
  write_mode();

  for(uint8_t i=0; i<BUFF_LEN; i++){
    setByte(addr+i, pageBuffer[i] & 0xff,chipId);
  }

  digitalWrite(OE, HIGH);
  digitalWrite(CE, HIGH);
  delayMicroseconds(35);

  check_buff(addr,chipId);
}

void check_buff(uint32_t addr,uint32_t chipId){

  read_mode();
  //读数据校验
  digitalWrite(CE, LOW);
  digitalWrite(OE, LOW);
  delayMicroseconds(10);
  boolean has_error = false;
  for(int i=0;i<BUFF_LEN ;i++){
    uint8_t rd = getByte(addr+i,chipId);
    if(pageBuffer[i]!=rd){
      Serial.print("0x");
      Serial.print(addr+i,HEX);
      Serial.print("=");
      Serial.print(rd,HEX);
      Serial.print(",not:");
      Serial.print(pageBuffer[i],HEX);
      Serial.print(" ");
      has_error = true;
    }
  }
  digitalWrite(CE, HIGH);
  digitalWrite(OE, HIGH);
}
